import utils from './index.js'

// Not a general-purpose deep copy function
function copyRecord(o) {
  const o2 = {}
  let val = null
  if (!o) return null
  for (let key in o) {
    if (o.hasOwnProperty(key)) {
      val = o[key]
      if (val == o) {
        // avoid infinite recursion if val is a circular reference, by copying all properties except key
        val = utils.extend({}, val)
        delete val[key]
      }
      o2[key] = val && val.constructor === Object ? copyRecord(val) : val
    }
  }
  return o2
}
// Fill out a data table with undefined values
// The undefined members will disappear when records are exported as JSON,
// but will show up when fields are listed using Object.keys()
function fixInconsistentFields(records) {
  const fields = findIncompleteFields(records)
  patchMissingFields(records, fields)
}
function findIncompleteFields(records) {
  const counts = {}
  let keys = null
  for (let i=0; i<records.length; i++) {
    keys = Object.keys(records[i] || {})
    for (let j=0; j<keys.length; j++) {
      counts[keys[j]] = (counts[keys[j]] | 0) + 1
    }
  }
  return Object.keys(counts).filter((k) => {return counts[k] < records.length})
}
function patchMissingFields(records, fields) {
  let rec = null
  let f = null
  for (let i=0; i<records.length; i++) {
    rec = records[i] || (records[i] = {})
    for (let j=0; j<fields.length; j++) {
      f = fields[j]
      if (f in rec === false) {
        rec[f] = undefined
      }
    }
  }
}
function deleteFields(table, test) {
  table.getFields().forEach((name) => {
    if (test(name)) {
      table.deleteField(name)
    }
  })
}
function getUniqFieldNames(fields, maxLen) {
  const used = {}
  return fields.map((name) => {
    let i = 0
    let validName = ''
    do {
      validName = adjustFieldName(name, maxLen, i)
      i++
    } while ((validName in used) || name !== validName && utils.contains(fields, validName))
    used[validName] = true
    return validName
  })
}
function adjustFieldName(name, maxLen, i) {
  let name2 = ''
  let suff = ''
  maxLen = maxLen || 256
  if (!i) {
    name2 = name.substr(0, maxLen)
  } else {
    suff = String(i)
    if (suff.length === 1) {
      suff = `_${suff}`
    }
    name2 = name.substr(0, maxLen - suff.length) + suff
  }
  return name2
}
function applyFieldOrder(arr, option) {
  if (option === 'ascending') {
    arr.sort(function(a, b) {
      return a.toLowerCase() < b.toLowerCase() ? -1 : 1
    })
  }
  return arr
};
function findFieldNames(records, order) {
  const first = records[0]
  const names = first ? Object.keys(first) : []
  return applyFieldOrder(names, order)
}
export default {
  deleteFields,
  getUniqFieldNames,
  findFieldNames,
  copyRecord,
  fixInconsistentFields,
}